package cn.yuysaln.domain.activity.service.partake;

import cn.yuysaln.domain.activity.model.aggregate.CreatePartakeOrderAggregate;
import cn.yuysaln.domain.activity.model.entity.ActivityEntity;
import cn.yuysaln.domain.activity.model.entity.PartakeRaffleActivityEntity;
import cn.yuysaln.domain.activity.model.entity.UserRaffleOrderEntity;
import cn.yuysaln.domain.activity.model.valobj.ActivityStateVO;
import cn.yuysaln.domain.activity.repository.IActivityRepository;
import cn.yuysaln.domain.activity.service.IRaffleActivityPartakeService;
import cn.yuysaln.types.enums.ResponseCode;
import cn.yuysaln.types.exception.AppException;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;

import java.util.Date;

/**
 * 定义参与活动，生成相应用户抽奖单、获得奖品一系列流程
 */
@Slf4j
public abstract class AbstractRaffleActivityPartake implements IRaffleActivityPartakeService {
    protected final IActivityRepository activityRepository; //构造注入
    public AbstractRaffleActivityPartake(IActivityRepository activityRepository) {
        this.activityRepository = activityRepository;
    }

    @Override
    public UserRaffleOrderEntity createUserRaffleOrder(PartakeRaffleActivityEntity partakeRaffleActivityEntity) {
        //获取基本信息方便之后流程使用
        String userId = partakeRaffleActivityEntity.getUserId();
        Long activityId = partakeRaffleActivityEntity.getActivityId();
        Date currentDate = new Date();

        //校验活动状态、日期
        ActivityEntity activityEntity = activityRepository.queryRaffleActivityByActivityId(activityId);
        if (!ActivityStateVO.open.equals(activityEntity.getState())) {
            throw new AppException(ResponseCode.ACTIVITY_STATE_ERROR.getCode(), ResponseCode.ACTIVITY_STATE_ERROR.getInfo());
        }
        if (activityEntity.getBeginDateTime().after(currentDate) || activityEntity.getEndDateTime().before(currentDate)) {
            throw new AppException(ResponseCode.ACTIVITY_DATE_ERROR.getCode(), ResponseCode.ACTIVITY_DATE_ERROR.getInfo());
        }

        //发起抽奖本身是一种对特定物品的下单行为
        //所以先查询是否有未完成订单
        UserRaffleOrderEntity userRaffleOrderEntity =  activityRepository.queryNoUsedRaffleOrder(partakeRaffleActivityEntity);
        if (null != userRaffleOrderEntity) {
            log.info("存在未消费活动订单  userId:{} activityId:{} userRaffleOrderEntity:{}", userId, activityId, JSON.toJSONString(userRaffleOrderEntity));
            return userRaffleOrderEntity;
        }

        //查询抽奖额度是否充足
        CreatePartakeOrderAggregate createPartakeOrderAggregate = this.doFilterAccount(userId, activityId, currentDate);

        //完成过滤则创建用户消费订单
        UserRaffleOrderEntity userRaffleOrder  = this.buildUserRaffleOrder(userId, activityId, currentDate);
        createPartakeOrderAggregate.setUserRaffleOrderEntity(userRaffleOrder);

        //生成聚合对象后进行落库存储（同一事务内）
        //生成抽奖单等于使用了一次额度，所以会对数据库的额度进行扣减
        activityRepository.saveCreatePartakeOrderAggregate(createPartakeOrderAggregate);

        return userRaffleOrder;
    }


    @Override
    public UserRaffleOrderEntity createUserRaffleOrder(String userId, Long activityId) {
        return createUserRaffleOrder(PartakeRaffleActivityEntity.builder()
                .userId(userId)
                .activityId(activityId)
                .build());
    }

    /**
     * 校验账户信息,查看抽奖额度是否足够
     * 构建聚合对象返回
     * @param userId
     * @param activityId
     * @param currentDate
     * @return 聚合对象包括 活动实体、相关次数额度
     */
    protected abstract CreatePartakeOrderAggregate doFilterAccount(String userId, Long activityId, Date currentDate);

    /**
     * 创建抽奖单实体对象
     * @param userId
     * @param activityId
     * @param currentDate
     * @return
     */
    protected abstract UserRaffleOrderEntity buildUserRaffleOrder(String userId, Long activityId, Date currentDate);
}
